/**
 * 
 * @props  {
 *  fill: 溢出点的填充内容，默认为...,
 *  fillClass: 溢出点的样式,
 *  position: 溢出点的位置 ['start', 'middle', 'end'], 默认为 end,
 *  showTitle: 鼠标悬停是否展示title ['always', 'none', 'auto'], 默认为 auto,
 *  scale: 是否自动缩小字体使文章能在单行中显示完整, 默认为false,
 *  rows: 文本保留的行数, 默认为1, 设置为0的话展示全文, 当设置了“scale” 或者 position="middle" 时, 此值无效
 *  content: 文本内容，优先级比默认插槽高,
 *  collapse: 折叠按钮的文本内容, 默认为“收起”,
 *  showCollapse: 展开的内容是否可被收起, 默认为false 不可收起,
 *  readonly: 内容只读不可展开, 默认关闭
 * } 
 * 
 * @events {
 *  change: 展开\收起的状态改变时的回调，返回值：Boolean--当前的状态
 * }
 */

import Ellipsis from './ellipsis'

export default {
  name: 'Ellipsis',
  props: {
    fill: {
      type: String,
      default: '...'
    },
    fillClass: {
      type: [String, Array],
    },
    position: {
      type: String,
      default: 'end',
      validator: value => ['start', 'middle', 'end'].indexOf(value) !== -1
    },
    showTitle: {
      type: String,
      default: 'auto',
      validator: value => ['always', 'none', 'auto'].indexOf(value) !== -1
    },
    rows: {
      type: Number,
      default: 1
    },
    scale: {
      type: Boolean,
      default: false
    },
    content: {
      type: String
    },
    collapse: {
      type: String,
      default: '收起'
    },
    showCollapse: {
      type: Boolean,
      default: false
    },
    readonly: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      _ellipsis: null,
      _showMore: false
    }
  },
  mounted() {
    this.$forceUpdate()
  },
  computed: {
    rawContent() {
      return this.content || this.getText()
    }
  },
  render(createElement) {
    if (!this.$el) {
      return createElement('div')
    }

    const spanVNode = this.createdFIllSpan(createElement)

    const ellipsis = this._ellipsis = new Ellipsis(this.rawContent, {
      el: this.$el,
      fill: spanVNode,
      rows: this.position === 'middle' || this.scale ? 0 : this.rows,
      position: this.position,
      scale: this.scale,
      showTitle: this.showTitle
    })
    const meta = ellipsis.meta

    if (this.rows === 0 || !meta || this._showMore) {
      const unfoldVNode = this.showCollapse ? [ellipsis.content, spanVNode] : ellipsis.content
      return this.doRender(createElement, false, unfoldVNode)
    }

    let hasEllipsis
    let ellipsisContent

    if (this.scale) {
      [hasEllipsis, ellipsisContent] = this.makeSvg(createElement)
    } else {
      [hasEllipsis, ellipsisContent] = ellipsis.make()
    }
    return this.doRender(createElement, hasEllipsis, ellipsisContent)
  },
  methods: {
    doRender(createElement, hasEllipsis, ellipsisContent) {
      this._ellipsis.destroy()
      let title = undefined
      if (this.showTitle === 'always' || (hasEllipsis && this.showTitle !== 'none')) {
        title = this.rawContent
      }
      return createElement('div', {
        attrs: {
          title
        }
      }, [ellipsisContent])
    },
    getText() {
      const content = this.$slots.default
      if (!content || content.length === 0) {
        return ''
      }
      return content.map(i => i.text).join('')
    },
    makeSvg(h) {
      const { baseline, viewBox, style, scaled } = this._ellipsis.getScaleInfo()

      return [scaled, h('svg', {
        attrs: { viewBox }
      }, [h('text', {
        attrs: { x: '0', y: baseline, style }
      }, this._ellipsis.content)])]
    },
    createdFIllSpan(createElement) {
      const parentScopedId = this.$parent.$options._scopeId
      return createElement('span', {
        attrs: {
          [parentScopedId]: parentScopedId
        },
        on: {
          click: this.handleShowMore
        },
        class: this.fillClass
      }, this._showMore ? this.collapse : this.fill)
    },
    handleShowMore() {
      if (this.readonly) return
      this._showMore = !this._showMore
      this.$emit('change', this._showMore)
      this.$forceUpdate()
    }
  },
  beforeDestroy() {
    if (this._ellipsis) {
      this._ellipsis.destroy()
    }
  }
}
